/*
 * Copyright zhoujun 2021 Wicrenet, Inc. All rights reserved.
 */
package com.ruoyi.netty.handler;

import com.ruoyi.netty.domain.DeviceChannelInfo;
import com.ruoyi.netty.domain.MsgAgreement;
import com.ruoyi.netty.utils.CacheService;
import com.ruoyi.netty.utils.CacheUtil;
import com.ruoyi.netty.utils.MsgUtil;
import com.ruoyi.netty.utils.NetWorkUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 【】
 *
 * @author zhoujun
 * Created on 2021/11/24 18:17
 */
@Component
public class SocketServerHandler extends SimpleChannelInboundHandler<String> {

    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private static List<String> userList = new ArrayList<>();
    @Autowired
    private CacheService cacheService;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.forEach(ch->{
            MsgAgreement msgAgreement = MsgUtil.json2Obj(msg);
            String toUserId = msgAgreement.getToUserId();
            //判断接收消息用户是否在本服务端
            Channel channel2 = CacheUtil.cacheChannel.get(toUserId);
            if (null != channel2) {
                if(channel2 != ch){
                    ch.writeAndFlush(channel.remoteAddress()+"发送消息："+msg);
                }else{
                    ch.writeAndFlush("【自己】"+msg);
                }
                return;
            }
            //如果为NULL则接收消息的用户不在本服务端，需要push消息给全局
            cacheService.push(msgAgreement);

        });
    }
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("【服务器】-"+channel.remoteAddress()+"加入");
        channelGroup.add(channel);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("【服务器】-"+channel.remoteAddress()+"离开");
        //channelGroup.remove(channel);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //Channel channel = ctx.channel();
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.out.println(channel.remoteAddress()+"上线");

        System.out.println("有一客户端链接到本服务端 channelId:" + channel.id());
        //保存设备信息
        DeviceChannelInfo deviceChannelInfo = new DeviceChannelInfo();
        deviceChannelInfo.setChannelId(channel.id().toString());
        deviceChannelInfo.setIp(NetWorkUtils.getHost());
        deviceChannelInfo.setPort(channel.localAddress().getPort());
        deviceChannelInfo.setLinkDate(new Date());
        cacheService.getRedisUtil().pushObj(deviceChannelInfo);
        CacheUtil.cacheChannel.put(channel.id().toString(), channel);
        ctx.writeAndFlush("ok \r\n");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        System.out.println(channel.remoteAddress()+"下线");
        System.out.println("客户端断开链接" + ctx.channel().id());
        cacheService.getRedisUtil().remove(ctx.channel().id().toString());
        CacheUtil.cacheChannel.remove(ctx.channel().id().toString(), ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
        cacheService.getRedisUtil().remove(ctx.channel().id().toString());
        CacheUtil.cacheChannel.remove(ctx.channel().id().toString(), ctx.channel());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent){
            IdleStateEvent event = (IdleStateEvent)evt;
            String eventType = null;
            switch (event.state()){
                case READER_IDLE:
                    eventType="读空闲";
                    break;
                case WRITER_IDLE:
                    eventType="写空闲";
                    break;
                case ALL_IDLE:
                    eventType="读写空闲";
                    break;
            }
            System.out.println(ctx.channel().remoteAddress()+"-"+eventType);
        }

    }
}
